package com.apobates.forum.core.dao;

import com.apobates.forum.core.entity.Album;
import com.apobates.forum.core.entity.ForumEntityStatusEnum;
import com.apobates.forum.core.entity.Posts;
import com.apobates.forum.core.entity.Topic;
import com.apobates.forum.core.entity.TopicTag;
import com.apobates.forum.core.entity.proxy.TopicReplica;
import com.apobates.forum.utils.persistence.Page;
import com.apobates.forum.utils.persistence.Pageable;
import com.apobates.forum.utils.persistence.PagingAndSortingRepository;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Stream;

/**
 * 话题的持久层接口
 *
 * @author xiaofanku
 * @since 20200510
 */
public interface TopicDao extends PagingAndSortingRepository<Topic, Long> {
    /**
     * 更新话题的状态枚举
     *
     * @param id 话题ID
     * @param status 更新的状态枚举
     * @return
     */
    Optional<Boolean> editStatus(long id, ForumEntityStatusEnum status);
    
    /**
     * 更新话题的置顶状态
     *
     * @param id 话题ID
     * @param topValue 更新的置顶状态值
     * @return
     */
    Optional<Boolean> editTop(long id, boolean topValue);
    
    /**
     * 更新话题的精华状态
     *
     * @param id 话题ID
     * @param goodsValue 更新的精华状态值
     * @return
     */
    Optional<Boolean> editGoods(long id, boolean goodsValue);
    
    /**
     * 更新话题的排序日期
     *
     * @param id 话题ID
     * @param updateDateTime 更新的日期
     * @return
     */
    Optional<Boolean> updateRankingDate(long id, LocalDateTime updateDateTime);
    
    /**
     * 移除话题关联的像册
     *
     * @param id 话题ID
     * @return
     */
    boolean removeAlbum(long id);
    
    /**
     * 移动话题到目标版块
     *
     * @param id 话题ID
     * @param targetBoardId 目标版块ID
     * @param targetBoardGroupId 目标版块所在版块组(卷)ID
     * @return 成功返回话题的回复数
     */
    int moveTopic(long id, long targetBoardId, int targetBoardGroupId);
    
    /**
     * 移除子栏目中指定的文章
     *
     * @since 20200427
     * @param id 子栏目的文章ID
     * @param termId 子栏目的ID
     * @return
     */
    Optional<Boolean> removeTermArticle(long id, long termId);
    
    /**
     * 编辑话题
     * @param topicId 编辑的话题ID
     * @param title 新的标题
     * @param content 新的话题内容
     * @param album 新的像册
     * @param tags 新的标签
     * @param modifyMember 编辑的会员ID
     * @param modifyMemberNickname 编辑的会员昵称
     */
    void modifyTopic(long topicId, String title, String content, Album album, Set<TopicTag> tags, long modifyMember, String modifyMemberNickname);
    
    /**
     * 保存话题
     * @param entity 话题
     * @param posts 话题内容
     * @param album 话题像册
     * @return 
     */
    Optional<TopicReplica> pushTopic(Topic entity, Posts posts, Album album);
    
    /**
     * 查看指定版块下的所有话题,不包括删除,置顶;包括加精,普通
     *
     * @param boardId 版块ID
     * @param pageable 分页请求参数
     * @return
     */
    Page<Topic> findAllByBoard(long boardId, Pageable pageable);
    
    /**
     *
     * @param boardId 版块ID
     * @param categoryValue 话题类型的Key(Topic.topicCategoryValue = TopicCategory.value)
     * @param pageable 分页请求参数
     * @return
     */
    Page<Topic> findAllByBoard(long boardId, String categoryValue, Pageable pageable);
    
    /**
     * [会员发布的话题]查看指定会员发布的话题,不计状态
     *
     * @param memberId 会员ID
     * @param pageable 分页请求参数
     * @return
     */
    Page<Topic> findAllByMember(long memberId, Pageable pageable);
    long findAllByMemberCount(long memberId);
    
    /**
     * [会员回复的话题]查看指定会员回复的话题,不包含话题的作者是该会员
     *
     * @param memberId 会员ID
     * @param pageable 分页请求参数
     * @return
     */
    Page<Topic> findAllByMemberReply(long memberId, Pageable pageable);
    long findAllByMemberReplyCount(long memberId);
    
    /**
     * 查看指定子栏目下的所有文章
     *
     * @since 20200427
     * @param termId 子栏目ID
     * @param pageable 分页请求参数
     * @return
     */
    Page<Topic> findAllTermArticle(long termId, Pageable pageable);
    
    /**
     * 根据标签 查看相关的话题
     *
     * @param tagNames 标签名集合
     * @param pageable 分页请求参数
     * @return
     */
    Page<Topic> findAllByTag(Collection<String> tagNames, Pageable pageable);
    
    /**
     * 查看指定日期范围内的话题,不包括删除的,不包含举报和反馈类型的.
     * 
     * @param start 开始日期
     * @param finish 结束日期
     * @param pageable 分页请求参数
     * @return 
     */
    Page<Topic> findAllByDate(LocalDateTime start, LocalDateTime finish, Pageable pageable);
    
    /**
     * 查看指定版块最近的话题,不包括删除;置顶;包括加精,普通;以rankingDateTime倒序
     *
     * @param boardId 版块ID
     * @param size 显示的数量
     * @return
     */
    Stream<Topic> findAllByBoard(long boardId, int size);
    
    /**
     * 查看指定版块最近的话题,忽略状态;以entryDateTime倒序
     *
     * @param boardId 版块ID
     * @param size 显示的数量
     * @return
     */
    Stream<Topic> findAllByBoardIgnoreStatus(long boardId, int size);
    
    /**
     * [版块新话题推送]自参考日期以后版块最近的话题
     *
     * @param boardId 版块ID
     * @param prevDate 参考日期
     * @return
     */
    Stream<Topic> findAllRecentByBoard(long boardId, LocalDateTime prevDate);

    /**
     * 自参考日期以后版块最近话题的数量
     *
     * @param boardId 版块ID
     * @param prevDate 参考日期
     * @return
     */
    long findAllRecentByBoardSize(long boardId, LocalDateTime prevDate);

    /**
     * 查看指定版块置顶的话题,不包括删除的
     *
     * @param boardId 版块ID
     * @return
     */
    Stream<Topic> findAllByBoardOfTop(long boardId);
    
    /**
     * [会员中心x.html]查看指定会员最近发布的话题,不包含删除的.按发布日期排序
     *
     * @param memberId 会员ID
     * @param size 显示的数量
     * @return
     */
    Stream<Topic> findAllByMember(long memberId, int size);
    
    /**
     * [会员中心x.html]查看指定会员最近回复的话题,不包含话题的作者是该会员
     *
     * @param memberId 会员ID
     * @param size 显示的数量
     * @return
     */
    Stream<Topic> findAllByMemberReply(long memberId, int size);
    
    /**
     * 查看会员发布的受欢迎的话题列表
     *
     * @param memberId 会员ID
     * @param size 显示的数量
     * @return
     */
    Stream<Topic> findAllByMemberPopular(long memberId, int size);
    
    /**
     * [站内动态]查看最近的话题,不包括删除的,不包含举报和反馈类型的
     *
     * @param size 显示的数量
     * @return
     */
    Stream<Topic> findAllOfRecent(int size);
    
    /**
     * [后台最近话题]查看最近的话题,忽略状态
     *
     * @param size 显示的数量
     * @return
     */
    Stream<Topic> findAllOfRecentIgnoreCondition(int size);
    
    /**
     * 查看指定版块组最近发布的话题,不包括删除的
     *
     * @param boardGroupId 版块组(卷)ID
     * @param size 显示的数量
     * @return
     */
    Stream<Topic> findAllOfRecent(int boardGroupId, int size);
    
    /**
     * 查看指定版块组的精华话题,不包含删除的
     *
     * @param boardGroupId 版块组(卷)ID
     * @param size 显示的数量
     * @return
     */
    Stream<Topic> findAllByBoardGroupOfGoods(int boardGroupId, int size);
    
    /**
     * 按回复日期查看指定数量的话题
     *
     * @param size 显示的数量
     * @return
     */
    Stream<Topic> findAllByReplyDate(int size);
    
    /**
     * 查看指定版块发布的话题,最先发布的排在最前面(Topic.entryDateTime ASC)
     *
     * @param boardId 版块ID
     * @param status 话题的状态
     * @return
     */
    Stream<Topic> findAllByBoard(long boardId, ForumEntityStatusEnum status);
    
    /**
     * 查看子栏目最近发布的文章
     *
     * @since 20200427
     * @param size 显示的数量
     * @return
     */
    Stream<Topic> findAllOfRecentTermArticle(int size);
    
    /**
     * 查看指定版块组中回复最多的话题,不包含删除的 回复的数量使用ranking属性
     *
     * @param boardGroupId 版块组(卷)ID
     * @param size 显示的数量
     * @return
     */
    List<Topic> findAllByBoardGroupByMaxReply(int boardGroupId, int size);
    
    /**
     * 查看回复最多的话题
     *
     * @param size 显示的数量
     * @return
     */
    List<Topic> findAllByMaxReply(int size);
    
    /**
     * 查看指定的话题
     *
     * @param idList 话题ID列表
     * @return
     */
    List<Topic> findAllById(Collection<Long> idList);
    
    /**
     * 查看指定的话题
     *
     * @param id 话题ID
     * @return
     */
    Topic findOneById(long id);
    
    /**
     * 查看栏目中的第一篇文章
     * @deprecated 
     * @since 20200427
     * @param termId 子栏目ID
     * @return
     */
    Optional<Topic> findOneArticleForTerm(long termId);
    
    /**
     * 查看子栏目中指定文章的下一篇
     *
     * @since 20200427
     * @param termId 子栏目ID
     * @param articleId 文章ID
     * @return
     */
    Optional<Topic> findNextTermArticle(long termId, long articleId);
    
    /**
     * 查看子栏目中指定文章的上一篇
     *
     * @since 20200427
     * @param termId 子栏目ID
     * @param articleId 文章ID
     * @return
     */
    Optional<Topic> findPrevTermArticle(long termId, long articleId);
    
    /**
     * 统计版块在指定日期的话题数量
     *
     * @param start 开始日期
     * @param finish 结束日期
     * @return Key=版块ID, Value=发布的话题合计,不计状态
     */
    Map<Long, Long> statsBoardTopicSize(LocalDateTime start, LocalDateTime finish);
    
    /**
     * 分组统计指定日期范围内的每日话题数量
     *
     * @param start 开始日期
     * @param finish 结束日期
     * @return Key=YYYY-MM-DD, Value=话题数量
     */
    TreeMap<String, Long> groupTopicSize(LocalDateTime start, LocalDateTime finish);
    
    /**
     * 统计版块在指定日期的话题数量
     *
     * @param boardId 版块ID
     * @param start 开始日期
     * @param finish 结束日期
     * @return
     */
    long statsBoardTopicSize(long boardId, LocalDateTime start, LocalDateTime finish);
    
    /**
     * 分组统计不同状态的话题数量
     *
     * @return Key=Topic.status, Value=话题数量
     */
    Map<ForumEntityStatusEnum, Long> groupTopicesForStatus();
    
    /**
     * 分组统计不同分类的话题数量
     *
     * @return Key=Topic.topicCategoryName, Value=话题数量
     */
    Map<String, Long> groupTopicesForCategory();
    
    /**
     * 分组统计不同版块的话题数量,版块统计内有此数据
     *
     * @return Key=Topic.boardId, Value=话题数量
     */
    Map<Long, Long> groupTopicesForBoard();
}